package com.edu.exam.entity.examination.online;

import com.edu.exam.enums.examination.ExamSessionState;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * 会话状态历史实体类
 *
 * <p>会话状态历史实体用于记录考试会话状态的变更历史，包括状态转换时间、
 * 转换原因、操作者等信息。确保会话状态变更的可追溯性和审计完整性。</p>
 *
 * <p>核心功能：
 * - 状态变更记录：完整记录每次状态变更的详细信息
 * - 转换原因跟踪：记录状态变更的原因和触发条件
 * - 操作者审计：记录执行状态变更的操作者信息
 * - 时间戳记录：精确记录状态变更的时间戳
 * - 变更日志：提供完整的状态变更日志和审计轨迹</p>
 *
 * @author 系统生成
 * @version 2.0
 * @since 2025-11-09
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class SessionStateHistory {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 会话ID
     *
     * <p>关联的考试会话ID，标识状态历史所属的会话。</p>
     */
    @Column(name = "session_id", nullable = false, length = 32)
    private String sessionId;

    /**
     * 原状态
     *
     * <p>变更前的会话状态。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "from_state", length = 20)
    private ExamSessionState fromState;

    /**
     * 新状态
     *
     * <p>变更后的会话状态。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "to_state", nullable = false, length = 20)
    private ExamSessionState toState;

    /**
     * 状态变更时间
     *
     * <p>状态变更发生的精确时间。</p>
     */
    @Column(name = "state_change_time", nullable = false)
    private LocalDateTime stateChangeTime;

    /**
     * 变更原因
     *
     * <p>状态变更的原因说明。
     * 用于说明状态变更的具体原因和背景。</p>
     */
    @Column(name = "change_reason", length = 500)
    private String changeReason;

    /**
     * 变更原因代码
     *
     * <p>状态变更原因的标准化代码。
     * 用于原因分类和统计分析。</p>
     */
    @Column(name = "change_reason_code", length = 50)
    private String changeReasonCode;

    /**
     * 变更类型
     *
     * <p>状态变更的类型。
     * 支持的类型：MANUAL（手动）、AUTOMATIC（自动）、SCHEDULED（定时）、EXCEPTION（异常）</p>
     */
    @Column(name = "change_type", nullable = false, length = 20)
    private String changeType = "MANUAL";

    /**
     * 操作者ID
     *
     * <p>执行状态变更的操作者ID。
     * 如果是自动变更，此字段可能为系统标识。</p>
     */
    @Column(name = "operator_id", length = 32)
    private String operatorId;

    /**
     * 操作者姓名
     *
     * <p>执行状态变更的操作者姓名。</p>
     */
    @Column(name = "operator_name", length = 100)
    private String operatorName;

    /**
     * 操作者类型
     *
     * <p>操作者的类型。
     * 支持的类型：USER（用户）、SYSTEM（系统）、SCHEDULED_TASK（定时任务）</p>
     */
    @Column(name = "operator_type", length = 20)
    private String operatorType = "USER";

    /**
     * 客户端IP地址
     *
     * <p>执行状态变更时的客户端IP地址。
     * 用于安全审计和来源追踪。</p>
     */
    @Column(name = "client_ip_address", length = 45)
    private String clientIpAddress;

    /**
     * 用户代理信息
     *
     * <p>执行状态变更时的用户代理信息。</p>
     */
    @Column(name = "user_agent", length = 500)
    private String userAgent;

    /**
     * 会话持续时间（秒）
     *
     * <p>从原状态到新状态的持续时间，单位为秒。
     * 用于分析各状态的持续时间。</p>
     */
    @Column(name = "state_duration_seconds")
    private Long stateDurationSeconds;

    /**
     * 触发条件
     *
     * <p>触发状态变更的条件。
     * 用于记录状态变更的触发条件。</p>
     */
    @Column(name = "trigger_condition", length = 500)
    private String triggerCondition;

    /**
     * 关联事件ID
     *
     * <p>关联的事件ID。
     * 用于关联触发状态变更的具体事件。</p>
     */
    @Column(name = "related_event_id", length = 32)
    private String relatedEventId;

    /**
     * 关联事件类型
     *
     * <p>关联事件的类型。</p>
     */
    @Column(name = "related_event_type", length = 50)
    private String relatedEventType;

    /**
     * 变更备注
     *
     * <p>状态变更的备注信息。
     * 记录额外的说明和注意事项。</p>
     */
    @Column(name = "change_notes", columnDefinition = "TEXT")
    private String changeNotes;

    /**
     * 变更参数
     *
     * <p>JSON格式的变更参数。
     * 记录状态变更时传递的参数信息。</p>
     */
    @Column(name = "change_parameters", columnDefinition = "TEXT")
    private String changeParameters;

    /**
     * 影响范围
     *
     * <p>状态变更的影响范围。
     * 描述状态变更对系统的影响范围。</p>
     */
    @Column(name = "impact_scope", length = 200)
    private String impactScope;

    /**
     * 是否为关键变更
     *
     * <p>标识是否为关键的状态变更。
     * true表示关键变更，false表示普通变更。</p>
     */
    @Column(name = "is_critical_change", nullable = false)
    private Boolean isCriticalChange = false;

    /**
     * 是否需要通知
     *
     * <p>标识是否需要发送通知。
     * true表示需要通知，false表示不需要通知。</p>
     */
    @Column(name = "notification_required", nullable = false)
    private Boolean notificationRequired = false;

    /**
     * 通知状态
     *
     * <p>通知的发送状态。
     * 支持的状态：NOT_REQUIRED（不需要）、PENDING（待发送）、SENT（已发送）、FAILED（失败）</p>
     */
    @Column(name = "notification_status", length = 20)
    private String notificationStatus = "NOT_REQUIRED";

    /**
     * 通知时间
     *
     * <p>通知的发送时间。</p>
     */
    @Column(name = "notification_time")
    private LocalDateTime notificationTime;

    /**
     * 通知接收者
     *
     * <p>通知的接收者列表，JSON格式。</p>
     */
    @Column(name = "notification_recipients", columnDefinition = "TEXT")
    private String notificationRecipients;

    /**
     * 状态标签
     *
     * <p>状态变更的标签，JSON格式。
     * 用于分类和过滤。</p>
     */
    @Column(name = "state_labels", columnDefinition = "TEXT")
    private String stateLabels;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;

  }